Статья про то, почему нужны import maps и как они работают.

На момент введение ES-модулей сообщество уже привыкло использовать пакеты из npm. При этом мы хотим писать код в браузере также, как пишем его обычно. И тут то и кроется конфликт.

Например, вы хотите импортировать библиотеку import lib from 'lib' - это то, как мы обычно делаем с npm. Однако в браузере нам бы необходимо было написать что-то вроде import lib from 'https://some.cdn.com/lib@1.0.0'.

Вот этот конфликт и решаются Import Maps. Они позволяют писать импорты в браузере также, как при использовании npm.

Например, на нашем примере это будет выглядеть так

<script type="importmap">
  {
    "lib": "https://some.cdn.com/lib@1.0.0"
  }
</script>
<script type="module">
import lib from 'lib';
</script>

При этом скрипт с Import Map должен быть вставлен до первого скрипта с type=module. Также, вместо того, чтобы описывать объект с мапингом прямо в тэге script, можно подтягивать Import Map через src, но при этом заголовок Content-Type должен быть выставлен в application/importmap+json

<script type="importmap" src="/importamap.json"></script>

Кроме того у Import Maps есть несколько фишек

Во первых, можно делать Import Map на группу пакетов. Например, на lodash

<script type="importmap">
{
  "imports": {
    "lodash/": "/node_modules/lodash-es/"
  }
}
</script>
<script type="module">
  import toUpper from 'lodash/toUpper.js';
  import toLower from 'lodash/toLower.js';
</script>

Во вторых, можно сделать алиасы на разные версии одного пакета

<script type="importmap">
  {
    "imports": {
      "lodash@3/": "https://unpkg.com/lodash-es@3.10.1/",
      "lodash@4/": "https://unpkg.com/lodash-es@4.17.21/"
    }
  }
</script>

Либо, можно предоставлять разные версии пакета для разных скриптов на основе path скрипта

<script type="importmap">
{
  "imports": {
    "lodash/": "https://unpkg.com/lodash-es@4.17.21/"
  },
  "scopes": {
    "/static/js": {
      "lodash/": "https://unpkg.com/lodash-es@3.10.1/"
    }
  }
}
</script>

Кроме того, можно формировать Import Map динамически

<script>
  const importMap = {
    imports: {
      lazyload: 'IntersectionObserver' in window
        ? './lazyload.js'
        : './lazyload-fallback.js',
    },
  };

  const im = document.createElement('script');
  im.type = 'importmap';
  im.textContent = JSON.stringify(importMap);
  document.currentScript.after(im);
</script>